from pathlib import Path
from typing import Optional, List

from openpyxl import load_workbook
from pydantic import BaseModel

from .export_as_excel import Exporter
from .import_from_excel import (
    import_products_from_tender,
    import_products_from_bid,
    unmerge_and_fill_cells,
)
from .process import add_supplier
from .schema import SummaryTable, BidTable

# 定义有效的工作表名称（根据实际业务需求调整）
AVAILABLE_SHEET_NAMES = ["报价单"]
HEADER_ROW = 4  # 表头所在行号


class Bidder(BaseModel):
    """投标供应商信息"""

    name: str
    document: Path
    has_bargaining: bool = False
    bargaining_document: Optional[Path] = None


class Consolidator:
    """报价数据整合处理器"""

    def __init__(self, tender_document: Path, summary_document: Path):
        self.tender_document = tender_document
        self.summary_document = summary_document
        self.summary_tables: List[SummaryTable] = []

    def load_tender(self):
        """加载招标文件（基准数据）"""
        tender_workbook = load_workbook(self.tender_document, data_only=True)

        for sheet_name in tender_workbook.sheetnames:
            if sheet_name not in AVAILABLE_SHEET_NAMES:
                continue

            sheet = tender_workbook[sheet_name]
            unmerge_and_fill_cells(sheet)

            try:
                # 验证表头结构
                self._validate_tender_header(sheet)

                # 导入产品数据
                summary_table = import_products_from_tender(sheet)
                self.summary_tables.append(summary_table)

            except Exception as e:
                print(f"Error processing tender sheet {sheet_name}: {str(e)}")
                raise

        tender_workbook.close()

    def _validate_tender_header(self, sheet):
        """验证招标文件表头结构（检查第4行）"""
        headers = [
            ("类别", 1),
            ("存货编码", 2),
            ("存货名称", 3),
            ("规格型号", 4),
            ("单位", 5),
            ("采购申请数量", 6),
        ]

        for header, col in headers:
            cell_value = str(sheet.cell(row=HEADER_ROW, column=col).value or "")
            if header not in cell_value:
                raise ValueError(
                    f"招标文件表头不符合要求，第{HEADER_ROW}行第{col}列应为'{header}'，实际为'{cell_value}'"
                )

    def add_bids(self, bid_documents: List[Bidder]):
        """添加投标文件数据"""
        for bidder in bid_documents:
            print(f"Processing bid from supplier: {bidder.name}")

            try:
                # 处理初轮报价
                self._add_bid(
                    supplier_name=bidder.name,
                    document=bidder.document,
                    is_bargaining=False,
                )

                # 处理二次议价（如果有）
                if bidder.has_bargaining and bidder.bargaining_document:
                    self._add_bid(
                        supplier_name=bidder.name,
                        document=bidder.bargaining_document,
                        is_bargaining=True,
                    )

            except Exception as e:
                print(f"Error processing bid from {bidder.name}: {str(e)}")
                raise

    def _add_bid(self, supplier_name: str, document: Path, is_bargaining: bool = False):
        """处理单个投标文件"""
        wb = load_workbook(document, data_only=True)

        for sheet_name in wb.sheetnames:
            if sheet_name not in AVAILABLE_SHEET_NAMES:
                continue

            sheet = wb[sheet_name]
            unmerge_and_fill_cells(sheet)

            try:
                # 验证投标文件表头
                self._validate_bid_header(sheet)

                # 导入投标数据
                bid_table = import_products_from_bid(
                    sheet=sheet, supplier=supplier_name, is_bargaining=is_bargaining
                )

                # 将投标数据添加到汇总表
                self._merge_to_summary(bid_table, supplier_name, is_bargaining)

            except Exception as e:
                wb.close()
                action = "二次议价" if is_bargaining else "初轮"
                raise ValueError(
                    f"{supplier_name}的{action}报价文件({sheet_name})格式错误: {str(e)}"
                )

        wb.close()

    def _validate_bid_header(self, sheet):
        """验证投标文件表头结构（检查第4行）"""
        required_headers = [
            ("类别", 1),
            ("存货编码", 2),
            ("存货名称", 3),
            ("规格型号", 4),
            ("单位", 5),
            ("采购申请数量", 6),
            ("报价", 7),
            ("总价", 8),
        ]

        for header, col in required_headers:
            cell_value = str(sheet.cell(row=HEADER_ROW, column=col).value or "")
            if header not in cell_value:
                raise ValueError(
                    f"第{HEADER_ROW}行第{col}列应为'{header}'，实际为'{cell_value}'"
                )

        # 检查必须包含单价列
        has_price = any(
            str(sheet.cell(row=HEADER_ROW, column=col).value or "") in ["报价", "单价"]
            for col in range(1, sheet.max_column + 1)
        )
        if not has_price:
            raise ValueError("缺少报价/单价列")

    def _merge_to_summary(
        self, bid_table: BidTable, supplier: str, is_bargaining: bool
    ):
        """将投标表合并到汇总表"""
        for summary_table in self.summary_tables:
            if summary_table.table_name == bid_table.table_name:
                # 添加供应商报价数据
                add_supplier(summary_table, bid_table)

                # 更新供应商列表
                if supplier not in summary_table.suppliers:
                    summary_table.suppliers.append(supplier)

                # 更新二次议价供应商列表
                if (
                    is_bargaining
                    and supplier not in summary_table.suppliers_with_bargaining
                ):
                    summary_table.suppliers_with_bargaining.append(supplier)

                return

        raise ValueError(f"找不到匹配的汇总表: {bid_table.table_name}")

    def save(self):
        """保存汇总结果到Excel文件"""
        # 打印汇总信息
        for table in self.summary_tables:
            print(
                f"汇总表: {table.table_name}, "
                f"产品数量: {len(table.products)}, "
                f"供应商数量: {len(table.suppliers)}"
            )

        # 导出Excel
        exporter = Exporter(self.summary_tables)
        exporter.export(str(self.summary_document))
